package levelEditor;

import com.jme3.app.SimpleApplication;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.niftygui.NiftyJmeDisplay;
import com.jme3.renderer.ViewPort;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.NiftyEventSubscriber;
import de.lessvoid.nifty.builder.ImageBuilder;
import de.lessvoid.nifty.builder.LayerBuilder;
import de.lessvoid.nifty.builder.PanelBuilder;
import de.lessvoid.nifty.builder.ScreenBuilder;
import de.lessvoid.nifty.controls.ButtonClickedEvent;
import de.lessvoid.nifty.controls.ListBox;
import de.lessvoid.nifty.controls.ListBoxSelectionChangedEvent;
import de.lessvoid.nifty.controls.TextField;
import de.lessvoid.nifty.controls.button.builder.ButtonBuilder;
import de.lessvoid.nifty.controls.label.builder.LabelBuilder;
import de.lessvoid.nifty.controls.listbox.builder.ListBoxBuilder;
import de.lessvoid.nifty.controls.textfield.builder.TextFieldBuilder;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;
import de.lessvoid.nifty.elements.Element;
import de.lessvoid.nifty.input.NiftyInputEvent;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public class EditorDialog implements ScreenController, ActionListener {

    private Nifty nifty;
    private EditorDialogInterface dialogInterface;
    private static final Logger logger = Logger.getLogger(EditorDialog.class.getName());
    
    private final String GUID_fileNameField = "GUID_fileNameField";
    private final String GUID_fileListBox = "GUID_fileListBox";
    private final String GUID_buttonSave = "GUID_buttonSave";
    private final String GUID_buttonLoad = "GUID_buttonLoad";
    private final String GUID_errorBox = "GUID_errorBox";
    private final String GUID_errorOk = "GUID_errorOk";
    

    public EditorDialog(SimpleApplication context, EditorDialogInterface dialogInterface, int xPos, int yPos) {
        Logger.getLogger(EditorDialog.class.getName()).setLevel(Level.INFO); // SEVERE  INFO
        final int x = xPos;
        final int y = yPos;
        
        this.dialogInterface = dialogInterface;
        final ScreenController editorScreenController = this; 


        context.getInputManager().addMapping("leftMouseNifty", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
        context.getInputManager().addListener(this, "leftMouseNifty");
        
        
        // IMPORTANT: Create a viewport which will be rendered after scene-graph
        // so that the nifty elements lay above the monkey stuff
        ViewPort niftyTopViewPort = context.getRenderManager().createPostView("Nifty view", context.getCamera());
        NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(context.getAssetManager(),
                                                           context.getInputManager(),
                                                           context.getAudioRenderer(),
                                                           niftyTopViewPort);
        nifty = niftyDisplay.getNifty();
        niftyTopViewPort.addProcessor(niftyDisplay);
        nifty.loadStyleFile("nifty-default-styles.xml");
        nifty.loadControlFile("nifty-default-controls.xml");

         Screen screen = new ScreenBuilder("start") {{
            controller(editorScreenController);
                // error box dialog
                layer(new LayerBuilder(GUID_errorBox) {{
                childLayoutCenter();

                image(new ImageBuilder() {{
                    filename("EditorTextures/risse.jpg");
                    width("10%");
                    height("10%");
                }});
                panel(new PanelBuilder() {{
                    //backgroundColor("#0000ffbb");
                    width("10%");
                    height("10%");
                    childLayoutVertical();
                    alignCenter();
                
                    control(new LabelBuilder(){{
                        color("#ffffffff"); 
                        wrap(true);
                        width("100%");
                        text("ERROR: File could not be loaded/saved");
                    }});
                    control(new ButtonBuilder(GUID_errorOk, "OK"){{
                        alignCenter();
                    }});
                }});
            }});
            
            
            // save load dialog
            layer(new LayerBuilder("loader_dialog") {{
                childLayoutAbsolute();
                
                panel(new PanelBuilder() {{
                    backgroundColor("#0000ffbb");
                    x(Integer.toString(x));
                    y(Integer.toString(y));
                    width("40%");
                    height("6%");
                    childLayoutHorizontal();
                
                    panel(new PanelBuilder() {{
                        width("5%");
                    }});
                        
                    panel(new PanelBuilder() {{
                        height("6%");
                        childLayoutVertical();
                        visibleToMouse(true);
                        interactOnClick("panelClicked()");

                        control(new LabelBuilder(){{
                            color("#ffff"); 
                            text("FILENAME");
                        }});

                        control(new TextFieldBuilder(GUID_fileNameField, "new") {{ 
                            maxLength(-1); 
                        interactOnClick("fileNameFieldClicked()");
                        }});

                        control(new ListBoxBuilder(GUID_fileListBox) {{
                            displayItems(8);
                            selectionModeSingle();
                            optionalHorizontalScrollbar();
                            optionalVerticalScrollbar();
                        }});

                    }});
                    
                    panel(new PanelBuilder() {{
                        width("5%");
                    }});
                    
                    panel(new PanelBuilder() {{
                        childLayoutVertical();
                        control(new LabelBuilder(){{
                                text("");
                        }});
                        control(new ButtonBuilder("GUID_buttonLoad", "LOAD"));
                    }});
                    
                    panel(new PanelBuilder() {{
                        width("5%");
                    }});

                    panel(new PanelBuilder() {{
                        childLayoutVertical();
                        control(new LabelBuilder(){{
                                text("");
                        }});
                        control(new ButtonBuilder("GUID_buttonSave", "SAVE"));
                    }});
                    
                    panel(new PanelBuilder() {{
                        width("5%");
                    }});
                }});
            }});
        }}.build(nifty);
         
    nifty.gotoScreen("start");
    
    Element listBox = nifty.getCurrentScreen().findElementByName(GUID_errorBox);
    listBox.setVisible(false);
    setVisibleErrorBox(false);
    populateFileListBox();
    setVisibleFileListBox(false);
    resetFocus();
    }
   
    
    private void resetFocus() {
        nifty.getCurrentScreen().getFocusHandler().resetFocusElements();
    }
    
    // when pressing mousse left outside the nifty gui -> close drop down and reset focus
    public void onAction(String name, boolean isPressed, float tpf) {
        if (name.equals("leftMouseNifty") && isPressed) {
            logger.log(Level.INFO, "mouse pressed", new Object[]{});
            setVisibleFileListBox(false);
            resetFocus();
        }
    }    

    //
    // LOAD/SAVE BUTTON interface functions
    //
    @NiftyEventSubscriber(id=GUID_buttonLoad)
    public void onLoadButton(final String id, final ButtonClickedEvent event) {
        logger.log(Level.INFO, "Load Button clicked", new Object[]{});
        boolean result;
        TextField fileNameField = nifty.getCurrentScreen().findNiftyControl(GUID_fileNameField, TextField.class);
        String fileName = fileNameField.getRealText();
        result = dialogInterface.dialogLoadFile(fileName);
        // error loading file happened. Show error Box
        if (!result){
            setVisibleErrorBox(true);
        }
    }

    @NiftyEventSubscriber(id=GUID_buttonSave)
    public void onSaveButton(final String id, final ButtonClickedEvent event) {
        logger.log(Level.INFO, "Save Button clicked", new Object[]{});
        boolean result;
        TextField fileNameField = nifty.getCurrentScreen().findNiftyControl(GUID_fileNameField, TextField.class);
        String fileName = fileNameField.getRealText();
        result = dialogInterface.dialogSaveFile(fileName);
        // error writing file happened. Show error Box
        if (!result){
            setVisibleErrorBox(true);
        }
        populateFileListBox();
    }
    
    //
    // FILE LIST & TEXTFIELD interface functions
    //
    
    // Element in file list selected
    // close box and copy selected name in text field
    @NiftyEventSubscriber(id=GUID_fileListBox)
    public void onListBoxSelectionChanged(final String id, final ListBoxSelectionChangedEvent event) {
        logger.log(Level.INFO, "list box changed: {0}", new Object[]{event.getSelection()});
        if (event.getSelection().size()>0){
            String selectedText = event.getSelection().get(0).toString();
            TextField fileNameField = nifty.getCurrentScreen().findNiftyControl(GUID_fileNameField, TextField.class);
            fileNameField.setText(selectedText);
        }
        setVisibleFileListBox(false);
        resetFocus();      
    }
    
    @NiftyEventSubscriber(id=GUID_fileNameField)
        //public void onTextFieldChangedEvent(final String id, final TextFieldChangedEvent event) {
    public void onTextFieldChangedEvent(final String id, final NiftyInputEvent  event) {
        logger.log(Level.INFO, "text box changed", new Object[]{});
        if(event.SubmitText.equals(event)){
            setVisibleFileListBox(false);
            resetFocus();
        }
    }

    public void fileNameFieldClicked() {
        logger.log(Level.INFO, "fileNameFieldClicked", new Object[]{});
        setVisibleFileListBox(true);
    } 

    public void panelClicked() {
        logger.log(Level.INFO, "panelClicked", new Object[]{});
        setVisibleFileListBox(false);
        resetFocus();   
    }

    private void setVisibleFileListBox(boolean visible) {
        Element listBox = nifty.getCurrentScreen().findElementByName(GUID_fileListBox);
        listBox.setVisible(visible);
        listBox.resetAllEffects();
    }

    private void populateFileListBox() {
        ListBox fileListBox = nifty.getCurrentScreen().findNiftyControl(GUID_fileListBox, ListBox.class);
        List<String> list = dialogInterface.dialogGetFileList();
        fileListBox.clear();
        for (int i = 0; i<list.size(); i++){
            fileListBox.addItem(list.get(i));
        }
    }
    
    //
    // ERROR BOX interface functions
    //
    private void setVisibleErrorBox(boolean visible) {
        Element box = nifty.getCurrentScreen().findElementByName(GUID_errorBox);
        box.setVisible(visible);
    }
    
    @NiftyEventSubscriber(id=GUID_errorOk)
    public void onOkButton(final String id, final ButtonClickedEvent event) {
        logger.log(Level.INFO, "Ok Button clicked", new Object[]{});
        setVisibleErrorBox(false);
    }
    
    //
    // SREEN interface functions
    //
    public void bind(Nifty nifty, Screen screen) {
        logger.log(Level.INFO, "bind", new Object[]{});
    }

    public void onStartScreen() {
        logger.log(Level.INFO, "onStartScreen", new Object[]{});
    }

    public void onEndScreen() {
        logger.log(Level.INFO, "onEndScreen", new Object[]{});
    }
}

